﻿using System;
using System.Collections;
using System.Collections.Generic;

namespace Runtime.Models {

    public interface IDFR_ReadOnlyDictionaryModel<TKey, TValue> : IDFR_Model, IReadOnlyDictionaryData<TKey, TValue> {
    }

    public interface IDFR_DictionaryModel<TKey, TValue> : IDFR_ReadOnlyDictionaryModel<TKey, TValue>, IDictionaryData<TKey, TValue> {
    }

    public abstract class DFR_DictionaryModel<TKey, TValue> : DFR_Model, IDFR_DictionaryModel<TKey, TValue> {

        [Autowired]
        private readonly IDictionaryData<TKey, TValue> m_Dictionary;

        #region Implement by m_Dictionary
        public TValue this[TKey key] { get => m_Dictionary[key]; set => m_Dictionary[key] = value; }

        TValue IReadOnlyDictionary<TKey, TValue>.this[TKey key] => ((IReadOnlyDictionary<TKey, TValue>)m_Dictionary)[key];

        public int Count => m_Dictionary.Count;

        public ICollection<TKey> Keys => m_Dictionary.Keys;

        public ICollection<TValue> Values => m_Dictionary.Values;

        public bool IsReadOnly => m_Dictionary.IsReadOnly;

        IEnumerable<TKey> IReadOnlyDictionary<TKey, TValue>.Keys => ((IReadOnlyDictionary<TKey, TValue>)m_Dictionary).Keys;

        IEnumerable<TValue> IReadOnlyDictionary<TKey, TValue>.Values => ((IReadOnlyDictionary<TKey, TValue>)m_Dictionary).Values;

        public event IDictionaryDataAdded<TKey, TValue>.AddedDelegate Added {
            add {
                m_Dictionary.Added += value;
            }

            remove {
                m_Dictionary.Added -= value;
            }
        }

        public event IDictionaryDataRemoved<TKey, TValue>.RemovedDelegate Removed {
            add {
                m_Dictionary.Removed += value;
            }

            remove {
                m_Dictionary.Removed -= value;
            }
        }

        public event IDictionaryDataCleared<TKey, TValue>.ClearedDelegate Cleared {
            add {
                m_Dictionary.Cleared += value;
            }

            remove {
                m_Dictionary.Cleared -= value;
            }
        }

        public event IDictionaryDataUpdated<TKey, TValue>.UpdatedDelegate Updated {
            add {
                m_Dictionary.Updated += value;
            }

            remove {
                m_Dictionary.Updated -= value;
            }
        }

        public void Add(TKey key, TValue value) {
            m_Dictionary.Add(key, value);
        }

        public void Add(KeyValuePair<TKey, TValue> item) {
            m_Dictionary.Add(item);
        }

        public IReadOnlyDictionaryData<TKey, TValue> AsReadOnly() {
            return m_Dictionary.AsReadOnly();
        }

        public IDictionaryData<TKey, TValue> AsReadWrite() {
            return m_Dictionary.AsReadWrite();
        }

        public void Clear() {
            m_Dictionary.Clear();
        }

        public bool Contains(KeyValuePair<TKey, TValue> item) {
            return m_Dictionary.Contains(item);
        }

        public bool ContainsKey(TKey key) {
            return m_Dictionary.ContainsKey(key);
        }

        public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex) {
            m_Dictionary.CopyTo(array, arrayIndex);
        }

        public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator() {
            return m_Dictionary.GetEnumerator();
        }

        public TValue GetValue(TKey key) {
            return m_Dictionary.GetValue(key);
        }

        public bool Remove(TKey key) {
            return m_Dictionary.Remove(key);
        }

        public bool Remove(KeyValuePair<TKey, TValue> item) {
            return m_Dictionary.Remove(item);
        }

        public bool TryAdd(TKey key, TValue value) {
            return m_Dictionary.TryAdd(key, value);
        }

        public bool TryAdd(KeyValuePair<TKey, TValue> item) {
            return m_Dictionary.TryAdd(item);
        }

        public bool TryGetValue(TKey key, out TValue value) {
            return m_Dictionary.TryGetValue(key, out value);
        }

        public void Update(TKey key, TValue value) {
            m_Dictionary.Update(key, value);
        }

        public void Update(TKey key, Action<TValue> updater) {
            m_Dictionary.Update(key, updater);
        }

        IEnumerator IEnumerable.GetEnumerator() {
            return ((IEnumerable)m_Dictionary).GetEnumerator();
        }
        #endregion
    }
}